package com.hm.base.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hm.base.auto.helper.ScheduleTriggerHandler;
import com.hm.base.auto.helper.SpringBeanUtil;
import com.hm.base.auto.su.BeanUtil;
import com.hm.base.def.ScheduleJobStatusEnum;
import com.hm.base.domain.ScheduleJob;
import com.hm.base.job.su.ScheduleJobTaskSupport;
import com.hm.base.mapper.ScheduleJobMapper;
import com.hm.base.vo.ScheduleJobVo;
import com.hm.common.def.DataStatusDef;
import com.hm.common.def.WhetherDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageParam;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.DateUtil;
import com.hm.common.util.StringUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 下午3:38:16 2017年8月24日
 * @version 1.0
 * @describe
 */
@Slf4j
@Service
public class ScheduleJobServiceImpl implements ScheduleJobService {

	@Autowired
	private ScheduleJobMapper scheduleJobMapper;

	@Autowired
	private ScheduleTriggerHandler scheduleTriggerHandler;

	@Override
	public void addScheduleJob(ScheduleJobVo scheduleJobVo) {
		if (CommonUtil.isEmpty(scheduleJobVo.getJobGroup())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ScheduleJob job = new ScheduleJob();
		job.setJobGroup(scheduleJobVo.getJobGroup());
		if (CommonUtil.isNotEmpty(scheduleJobMapper.select(job))) {
			throw ServiceException.warning(ErrorCode.DATA_EXISTING);
		}

		BeanUtil.copyProperties(scheduleJobVo, job);
		job.setId(null);
		job.setCreateTime(new Date());
		job.setJobStatus(ScheduleJobStatusEnum.ENABLE.name());
		job.setStatus(DataStatusDef.ENABLE.name());
		job.setRealTime(StringUtil.isBlank(job.getRealTimeHandler()) ? WhetherDef.NO.name() : WhetherDef.YES.name());

		scheduleJobMapper.insert(job);

		if (CommonUtil.isAnyEmpty(job.getJobName(), job.getJobGroup(), job.getCron())) {
			return;
		}
		scheduleTriggerHandler.addScheduleJob(job.getJobName(), job.getJobGroup(), job.getCron());
	}

	@Override
	public void updateScheduleJob(Long scheduleJobId, ScheduleJobVo scheduleJobVo) {
		if (CommonUtil.isAnyEmpty(scheduleJobId, scheduleJobVo.getJobGroup())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ScheduleJob job = new ScheduleJob();
		job.setJobGroup(scheduleJobVo.getJobGroup());
		ScheduleJob scheduleJob = scheduleJobMapper.selectOne(job);
		if (CommonUtil.isNotEmpty(scheduleJob) && scheduleJob.getId() != scheduleJobId) {
			throw ServiceException.warning(ErrorCode.DATA_EXISTING);
		}

		if (!CommonUtil.isAnyEmpty(scheduleJob.getJobName(), scheduleJob.getJobGroup(), scheduleJob.getCron())) {
			scheduleTriggerHandler.deleteScheduleJob(scheduleJob.getJobName(), scheduleJob.getJobGroup());
		}

		scheduleJob.setCron(scheduleJobVo.getCron());
		scheduleJob.setNote(scheduleJobVo.getNote());
		job.setRealTime(StringUtil.isBlank(job.getRealTimeHandler()) ? WhetherDef.NO.name() : WhetherDef.YES.name());
		scheduleJobMapper.updateByPrimaryKey(scheduleJob);

		if (!scheduleJob.getJobStatus().equals(ScheduleJobStatusEnum.ENABLE.name())
				|| CommonUtil.isAnyEmpty(scheduleJob.getJobName(), scheduleJob.getJobGroup(), scheduleJob.getCron())) {
			return;
		}
		scheduleTriggerHandler.addScheduleJob(scheduleJob.getJobName(), scheduleJob.getJobGroup(),
				scheduleJob.getCron());
	}

	@Override
	public void updateScheduleJobStatus(Long scheduleJobId, ScheduleJobStatusEnum scheduleJobStatus) {
		if (CommonUtil.isAnyEmpty(scheduleJobId, scheduleJobStatus)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ScheduleJob scheduleJob = scheduleJobMapper.selectByPrimaryKey(scheduleJobId);
		if (CommonUtil.isEmpty(scheduleJob)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		scheduleJob.setJobStatus(scheduleJobStatus.name());
		scheduleJobMapper.updateByPrimaryKey(scheduleJob);

		if (CommonUtil.isAnyEmpty(scheduleJob.getJobName(), scheduleJob.getJobGroup(), scheduleJob.getCron())) {
			return;
		}

		switch (scheduleJobStatus) {
		case DISABLE:
			scheduleTriggerHandler.deleteScheduleJob(scheduleJob.getJobName(), scheduleJob.getJobGroup());
			break;
		case ENABLE:
			scheduleTriggerHandler.updateScheduleJob(scheduleJob.getJobName(), scheduleJob.getJobGroup(),
					scheduleJob.getCron());
			break;
		case PAUSE:
			scheduleTriggerHandler.pauseScheduleJob(scheduleJob.getJobName(), scheduleJob.getJobGroup());
			break;
		default:
			break;
		}
	}

	@Override
	public void deleteScheduleJob(List<Long> scheduleJobIds) {
		if (CommonUtil.isEmpty(scheduleJobIds)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		scheduleJobIds.parallelStream().forEach(scheduleJobId ->{
			
			ScheduleJob scheduleJob = scheduleJobMapper.selectByPrimaryKey(scheduleJobId);
			if (CommonUtil.isEmpty(scheduleJob)) {
				return;
			}

			scheduleJob.setJobStatus(ScheduleJobStatusEnum.DISABLE.name());
			scheduleJob.setStatus(DataStatusDef.DISABLE.name());
			scheduleJobMapper.updateByPrimaryKey(scheduleJob);

			if (CommonUtil.isAnyEmpty(scheduleJob.getJobName(), scheduleJob.getJobGroup(), scheduleJob.getCron())) {
				return;
			}
			scheduleTriggerHandler.deleteScheduleJob(scheduleJob.getJobName(), scheduleJob.getJobGroup());
		});
		
	}

	@Override
	public ScheduleJobVo getScheduleJob(Long scheduleJobId) {
		if (CommonUtil.isEmpty(scheduleJobId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ScheduleJob scheduleJob = scheduleJobMapper.selectByPrimaryKey(scheduleJobId);
		if (CommonUtil.isEmpty(scheduleJob)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}
		ScheduleJobVo vo = new ScheduleJobVo();
		BeanUtil.copyProperties(scheduleJob, vo);
		vo.setScheduleJobStatus(ScheduleJobStatusEnum.trance(scheduleJob.getJobStatus()));
		vo.setWhetherRealTime(WhetherDef.trance(scheduleJob.getRealTime()));
		vo.setCreateTime(DateUtil.data2long(scheduleJob.getCreateTime()));

		return vo;
	}

	@Override
	public PageInfo<ScheduleJobVo> query(PageParam pageParam, String jobGroup,
			ScheduleJobStatusEnum scheduleJobStatus) {
		Page<ScheduleJob> page = PageHelper.startPage(pageParam.getPage(), pageParam.getSize(), true);

		ScheduleJob scheduleJob = new ScheduleJob();
		if (CommonUtil.isNotEmpty(jobGroup)) {
			scheduleJob.setJobGroup(jobGroup);
		}
		if (CommonUtil.isNotEmpty(scheduleJobStatus)) {
			scheduleJob.setJobStatus(scheduleJobStatus.name());
		}

		scheduleJobMapper.query(scheduleJob);
		List<ScheduleJobVo> vos = new ArrayList<ScheduleJobVo>();
		page.getResult().forEach(item -> {
			ScheduleJobVo vo = new ScheduleJobVo();
			BeanUtil.copyProperties(item, vo);
			vo.setCreateTime(DateUtil.data2long(item.getCreateTime()));
			vo.setWhetherRealTime(WhetherDef.trance(item.getRealTime()));
			vo.setScheduleJobStatus(ScheduleJobStatusEnum.trance(item.getJobStatus()));

			vos.add(vo);
		});

		return new PageInfo<ScheduleJobVo>(vos, page.getPages(), page.getTotal());
	}

	@Override
	public void realTimeScheduleJob(Long scheduleJobId) {
		if (CommonUtil.isEmpty(scheduleJobId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ScheduleJob scheduleJob = scheduleJobMapper.selectByPrimaryKey(scheduleJobId);
		if (CommonUtil.isEmpty(scheduleJob)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		if (CommonUtil.isEmpty(scheduleJob.getRealTimeHandler())
				|| WhetherDef.trance(scheduleJob.getRealTime()) == WhetherDef.NO) {
			throw ServiceException.warn("当前调度任务不支持及时调用");
		}

		try {
			ScheduleJobTaskSupport scheduleJobTaskSupport = (ScheduleJobTaskSupport) SpringBeanUtil
					.getBean(Class.forName(scheduleJob.getRealTimeHandler()));
			scheduleJobTaskSupport.doTask();
		} catch (ClassNotFoundException e) {
			log.error(e.getMessage(), e);
		}
	}

}
